/*
 * prueba.c
 *
 *  Created on: 14/09/2011
 *      Author: fabian
 */
/*
#include "fat-utils.h"
#include <iconv.h>
#include <wchar.h>

int isClusterEnd(uint32_t value){
	return (value & 0x0FFFFFFF) >= 0x0FFFFFF8;
}

int isClusterFree(uint32_t value){
	return (value & 0x0FFFFFFF) == 0x00000000;
}

int isClusterBad(uint32_t value){
	return value == 0x0FFFFFF7;
}

//TODO revisar esta funcion pq el EOCluster puede contener datos.
int isLegalCluster(uint32_t value){
	return !(isClusterEnd(value) || isClusterEnd(value) || isClusterFree(value) || isClusterBad(value));
}

uint32_t getFatSector(BPB * bpbPtr, uint32_t clusterNum){
	uint32_t count = bpbPtr->BPB_ResvdSecCnt + ((clusterNum * 4) / bpbPtr->BPB_BytsPerSec);
//	printf("Obteniendo sector de cluster %d , sector %d\n",clusterNum,count);
	return count;
}

uint32_t getFatSectorOffset (BPB * bpbPtr, uint32_t clusterNum) {
	uint32_t count = (clusterNum * 4) % bpbPtr->BPB_BytsPerSec;
//	printf("Obteniendo offset en sector de cluster %d , sector %d\n",clusterNum,count);
	return count;
}

uint32_t getFatInfoOffset(BPB * bpbPtr, uint32_t clusterNum) {
	uint32_t secOffset = (bpbPtr->BPB_BytsPerSec * getFatSector(bpbPtr,clusterNum));
	uint32_t count = secOffset + getFatSectorOffset(bpbPtr,clusterNum);
//	printf("Obteniendo offset total de cluster %d, offset sector %d, offset total %d\n",clusterNum,secOffset,count);
	return count;
}

uint32_t getCantSecReservados(BPB *bootSector){
	return bootSector->BPB_ResvdSecCnt + (bootSector->BPB_NumFATs * bootSector->BPB_FATSz32);
}

uint32_t getOffsetCluster(BPB *bootSector, uint32_t clusterNumber){
	return (getCantSecReservados(bootSector) + (clusterNumber - 2) * bootSector->BPB_SecPerClus) * bootSector->BPB_BytsPerSec;
}

char * utf2char(uint16_t * instr, uint isize, uint osize){

	iconv_t des;
	uint16_t *inbuf;
	char * outbuf;
	char * outptr;
	uint insize=isize;
	uint outputbufsize=osize;
	uint avail=outputbufsize;
	uint nconv;

	inbuf=instr;
	outbuf=(char *)calloc(outputbufsize,sizeof(char));
	outptr=outbuf;

	des=iconv_open("ascii","utf-16");
	if(des==(iconv_t)-1)
	{
			perror("fail.\n");
	}
	nconv=iconv(des,&inbuf,&insize,&outptr,&avail);
	perror("algo");
	printf("[%s]\n",outbuf);
	iconv_close(des);
	return outbuf;
}

void printRootDir( DirEntry * dir){
	puts("Detalles del directorio:");
	printf("\t0: %c\n", dir->DIR_Name[0]);
	printf("\t1: %c\n", dir->DIR_Name[1]);
	printf("\t2: %c\n", dir->DIR_Name[2]);
	printf("\t3: %c\n", dir->DIR_Name[3]);
	printf("\t4: %c\n", dir->DIR_Name[4]);
	printf("\t5: %c\n", dir->DIR_Name[5]);
	printf("\t6: %c\n", dir->DIR_Name[6]);
	printf("\t7: %c\n", dir->DIR_Name[7]);
	printf("\t8: %c\n", dir->DIR_Name[8]);
	printf("\t9: %c\n", dir->DIR_Name[9]);
	printf("\t0: %c\n", dir->DIR_Name[10]);
	printf("\t11: %c\n", dir->DIR_Name[11]);
	if ( (dir->DIR_Attr & 0x08) == 8)
		puts("Es el root directory");
	printf("\tAttribute is %d\n",dir->DIR_Attr);
	printf("\tNT Reserved is %d\n",dir->DIR_NTRes);
	printf("\tMiliseconds is %d\n",dir->DIR_CrtTimeTenth);
	printf("\tCreation time is %d\n",dir->DIR_CrtTime);
	printf("\tCreation date is %d\n",dir->DIR_CrtDate);
	printf("\tLast access date is %d\n",dir->DIR_LstAccDate);
	printf("\tFirst Cluser HI is %d\n",dir->DIR_FstClusHI);
	printf("\tLast write time is %d\n",dir->DIR_WrtTime);
	printf("\tLast write date is %d\n",dir->DIR_WrtDate);
	printf("\tFirst Cluster LO is %d\n",dir->DIR_FstClusLO);
	printf("\tFilesize is %d\n",dir->DIR_FileSize);
	printf("\n");
}

int main(void){

	BPB bootSector;
	FSInfo infoSector;
	uint32_t offset = 0;
	uint32_t * secLibres;

	int fileHandle = open("/vfs/fat32.disk.0", O_RDONLY);
	if( fileHandle < 0){
		perror("Error opening disk.");
		return 1;
	}


	int res = read(fileHandle , &bootSector, sizeof(BPB));

	if( res != sizeof(BPB) ){
		printf("Error reading from disk.%d",res);
		return 1;
	}

	offset = bootSector.BPB_FSInfo * bootSector.BPB_BytsPerSec;

	res = lseek(fileHandle, offset, SEEK_SET);

	res = read(fileHandle , &infoSector, sizeof(FSInfo));
	if( res != sizeof(FSInfo) ){
		printf("Error reading from disk FS.%d",res);
		return 1;
	}

	uint32_t fatSize = bootSector.BPB_FATSz32;
	// uint32_t totalSec = bootSector.BPB_TotSec32;
	// uint32_t RootDirSectors = ( ( bootSector.BPB_RootEntCnt * 32 ) + ( bootSector.BPB_BytsPerSec - 1 ) ) / bootSector.BPB_BytsPerSec;
	uint32_t DataSec = bootSector.BPB_TotSec32 - (bootSector.BPB_ResvdSecCnt + (bootSector.BPB_NumFATs * fatSize));
	//uint32_t secReservados = getCantSecReservados(&bootSector);
	uint32_t clustCount = DataSec / bootSector.BPB_SecPerClus;

	//armar la lista de los sectores libres.
	secLibres = (uint32_t *)calloc(clustCount,sizeof(uint32_t));
	uint32_t currSec = infoSector.FSI_Nxt_Free;
	uint32_t index = 0;
	for(;currSec < clustCount; currSec++){
		uint32_t value = 0;
		offset = getFatInfoOffset(&bootSector,currSec);
		res = lseek(fileHandle, offset, SEEK_SET);
		if(res == -1) { perror("en seek"); break; }
		res = read(fileHandle , &value, sizeof(uint32_t));
		if(res == -1) { perror("en en read"); break; }

		if(isClusterFree(value))
			secLibres[index++] = currSec;
	}
	//imprimir la lista de sectores libres
	printf("Lista de clusters libres\n");
	index=0;
	int corte = 0;
	while(secLibres[index] != 0){
		printf("%d\t",secLibres[index]);
		index++;
		corte++;
		if(corte == 20){
			corte = 0;
			printf("\n");
		}
	}
	printf("\nFin lista de clusters libres");

	//obtener el directorio root
	DirEntry rootDir;
	offset = getOffsetCluster(&bootSector,bootSector.BPB_RootClus);
	printf("Cluster Root offset %d\n",offset);
	res = lseek(fileHandle, offset, SEEK_SET);
	if(res == -1) { perror("en seek"); }
	res = read(fileHandle , &rootDir , sizeof(DirEntry));
	if(res == -1) { perror("en en read"); }
	int a = rootDir.DIR_Attr & 0x08;
	if (a == 8)
		puts("Root dir!!!");
	LDirEntry lodir;
	res = read(fileHandle , &lodir , sizeof(LDirEntry));
	if(res == -1) { perror("en en read"); }
	uint16_t nombre[14];
	char texto[14];
	bzero(texto,14*sizeof(uint8_t));
	uint16_t * lug = nombre;
	bzero(nombre,14*sizeof(uint16_t));

	printf("%s\n",utf2char(lodir.LDIR_Name1,5*sizeof(uint16_t),5));

	printRootDir(&rootDir);

	//armar el arbol de directorio con los archivos y los clusters ocupados por cada uno



	//imprimir el arbol de directorios en forma de arbolito.

	close(fileHandle);
	return 0;
}
*/
